/* Copyright (C) 2015-2016 HangZhou Zenzet Technology Co., Ltd.
 * All right reserved

 * File:crypto/locketstreamcrypt.c
 * Author:guojianchuan/max
 * Date:2016-06-02

 */

/* system header */
#include <string.h>
#include <stdlib.h>

/* 3rd project header */
#include "openssl/evp.h"
#include "openssl/aes.h"

/* my project header */
#include "locketdef.h"
#include "locketerrno.h"
#include "locketlog.h"
#include "locketcommon.h"

#include "locketstreamcrypt.h"

/**
* @struct: DECRYPT_STATE_S
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: 流加密状态机
*/
typedef struct tagEncryptState
{
    /* 是否已经开始加密的标识 */
    int iStartEnc;
}ENCRYPT_STATE_S;

/**
* @struct: DECRYPT_STATE_S
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: 流解密状态机
*/
typedef struct tagDecryptState
{
    /* 解析状态 */
    int iStep;

    /* 解析出来的meta信息保存在这里 */
    META_S stMeta;

    /* header parse offset */
    int iHdrParseOffSet;

    /* header parse buffer */
    char szHdrParseBuf[HEADER_TAG_LEN];

    /* meta_len parse offset */
    int iMetaLenParseOffSet;

    /* meta_len parse buffer */
    char szMetaLenParseBuf[META_LEN_SIZE];

    /* meta parse offset */
    int iMetaParseOffSet;

    /* meta parse buffer */
    char szMetaParseBuf[META_SIZE];

    /* cipher prefix parse offset */
    int iCipherPrefixParseOffSet;

    /* cipher prefix parse buffer */
    char szCipherPrefixParseBuf[ENCRYPT_TAG_LEN];

    /* cipher data parse offset */
    int iCipherDataParseOffset;

    /* cipher data parse buffer(need malloc) */
    unsigned char szCipherDataParseBuf[DECRYPT_BLOCK_SIZE + ENCRYPT_TAG_LEN];

    /* 是否已经开始解密的标识 */
    int iStartDec;
}DECRYPT_STATE_S;

/**
* @struct: STREAM_CTX_S
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: 流加解密上下文
*/
typedef struct tagStreamCryptCtx
{   
    /* cipher上下文 */
    EVP_CIPHER_CTX *pstCipherCtx;

    /* 加密信息 */
    CIPHER_STREAM_S stCryptInfo;

    /* 辅助字段 */
    char *pcData;

    /* len */
    int iDataLen;

    /* 加密状态(只在流加密过程中需要用到) */
    ENCRYPT_STATE_S stEncState;

    /* 解密状态(只在流解密过程中需要用到) */
    DECRYPT_STATE_S stDecState;
}STREAM_CTX_S;

extern int LOCKET_CIPHER_BuildHeaderMeta(IN META_S* pstMeta, OUT char *pcOutput, OUT int *piOutLen);
extern int LOCKET_CIPHER_ParseFileMeta(IN char *pcMeta, OUT META_S *pstMeta);

/**
* @Function:LOCKET_CIPHER_StreamEncryptInit
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: AES encrypt for stream
* @caution: 
*/
CRYPT_HANDLE LOCKET_CIPHER_StreamEncryptInit(IN CIPHER_STREAM_S *pstStreamCrypt, IN META_S *pstMeta)
{
    if ((NULL == pstStreamCrypt) ||
        (NULL == pstStreamCrypt->pfCryptCBFunc) ||
        (NULL == pstMeta))
    {
        return 0;
    }

    int iErr = ERR_COMMON_SUCCESS;

    STREAM_CTX_S *pstCtx = LOCKET_malloc (sizeof (STREAM_CTX_S));
    if (NULL == pstCtx)
    {
        return 0;
    }
    memset (pstCtx, 0, sizeof (STREAM_CTX_S));

    const EVP_CIPHER *pstCipher  = NULL;
    EVP_CIPHER_CTX *pstCipherCtx = NULL;

    do 
    {
        /* 构造头和meta信息 */
        int iHeaderMetaLen = 0;
        char szHeaderMeta[HEADERMETA_SIZE] = {0};
        iErr = LOCKET_CIPHER_BuildHeaderMeta (pstMeta, szHeaderMeta, &iHeaderMetaLen);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("build header/meta failed. err:%d", iErr);
            break;
        }

        /* 初始化加密算法 */
        pstCipher    = EVP_get_cipherbyname(CRYPT_ALGORITHM);
        pstCipherCtx = EVP_CIPHER_CTX_new ();
        iErr = EVP_CipherInit_ex(pstCipherCtx, pstCipher, NULL, 
                                 pstMeta->stCipher.szKey, pstMeta->stCipher.szIv, 1);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherInit_ex failed. %s", LOCKET_ERR_GetString());
            break;
        }

        CB_PARAM_S stParam = {0};
        stParam.pcData     = (char*) szHeaderMeta;
        stParam.iParamLen  = iHeaderMetaLen;
        (*pstStreamCrypt->pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

    } while (0);

    if (ERR_COMMON_SUCCESS != iErr)
    {
        LOCKET_free ((void**) &pstCtx);
    }

    memcpy (&pstCtx->stCryptInfo ,pstStreamCrypt, sizeof (CIPHER_STREAM_S));
    pstCtx->pstCipherCtx = pstCipherCtx;

    return (CRYPT_HANDLE) pstCtx;
}

/**
* @Function:LOCKET_CIPHER_StreamEncryptUpdate
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: AES encrypt for stream
* @caution:  如果是最后一次调用，需要设置iLastBlock=1
*/
int LOCKET_CIPHER_StreamEncryptUpdate (CRYPT_HANDLE hCrypt, char *pcData, int iLen, int iLastBlock)
{
    if ((NULL == hCrypt) || (NULL == pcData) || (0 == iLen))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr             = ERR_COMMON_SUCCESS;
    STREAM_CTX_S *pstCtx = (STREAM_CTX_S*) hCrypt;

    /* 
     * 1.为了减少频繁的malloc操作，默认使用同一块内存，当内存较小
     *   的时候，才重新申请内存 
     * 2.内存释放，在LOCKET_CIPHER_StreamCryptFree中进行
     */
    if ((NULL == pstCtx->pcData) || (pstCtx->iDataLen < iLen))
    {
        LOCKET_free ((void**) &pstCtx->pcData);
        pstCtx->pcData = LOCKET_malloc (iLen);
        if (NULL == pstCtx->pcData)
        {
            return ERR_COMMON_NO_MEM;
        }
        pstCtx->iDataLen = iLen;
    }

    CB_PARAM_S stParam;
    /* 只在第一次，生成密文头 */
    if (0 == pstCtx->stEncState.iStartEnc)
    {
        char szCipherHeader[ENCRYPT_TAG_LEN] = ENCRYPT_PREFIX_TAG;
        stParam.pcData   = (char*) szCipherHeader;
        stParam.iParamLen = sizeof (szCipherHeader);
        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);
        pstCtx->stEncState.iStartEnc = 1;
    }

    /* 密文加密 */
    iErr = EVP_CipherUpdate(pstCtx->pstCipherCtx, (unsigned char*) pstCtx->pcData, &pstCtx->iDataLen, (unsigned char*) pcData, iLen);
    if (ERR_COMMON_SUCCESS != iErr)
    {
        LOCKET_LOGERROR ("EVP_CipherUpdate failed. %s", LOCKET_ERR_GetString());
        return iErr;
    }
    stParam.pcData = pstCtx->pcData;
    stParam.iParamLen = pstCtx->iDataLen;
    (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

    if (1 == iLastBlock)
    {
        iErr = EVP_CipherFinal_ex(pstCtx->pstCipherCtx, (unsigned char*)(pstCtx->pcData + pstCtx->iDataLen), &pstCtx->iDataLen);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherFinal_ex failed. %s", LOCKET_ERR_GetString());
            return iErr;
        }

        stParam.pcData      = pstCtx->pcData;
        stParam.iParamLen   = pstCtx->iDataLen;
        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

        /* 构造密文尾 */
        char szCipherEnd[ENCRYPT_TAG_LEN] = ENCRYPT_SUFFIX_TAG;
        stParam.pcData    = szCipherEnd;
        stParam.iParamLen = sizeof (szCipherEnd);
        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_FINISH, NULL);
    }

    return ERR_COMMON_SUCCESS;
}

/**
* @Function:LOCKET_CIPHER_StreamDecryptInit
* @Author: guojianchuan/max
* @Date: 2016-07-22
* @Description: AES decrypt for stream
* @caution: 
*/
CRYPT_HANDLE LOCKET_CIPHER_StreamDecryptInit(IN CIPHER_STREAM_S *pstStreamCrypt)
{
    if ((NULL == pstStreamCrypt) ||
        (NULL == pstStreamCrypt->pfCryptCBFunc))
    {
        return 0;
    }

    EVP_CIPHER_CTX *pstCipherCtx = EVP_CIPHER_CTX_new ();    
    STREAM_CTX_S *pstCtx = LOCKET_malloc (sizeof (STREAM_CTX_S));
    if (NULL == pstCtx)
    {
        return 0;
    }
    memset (pstCtx, 0, sizeof (STREAM_CTX_S));
    
    memcpy (&pstCtx->stCryptInfo ,pstStreamCrypt, sizeof (CIPHER_STREAM_S));
    pstCtx->pstCipherCtx = pstCipherCtx;

    pstCtx->stDecState.iStep = PARSE_HEADER;

    return (CRYPT_HANDLE) pstCtx;
}

/**
* @Function:LOCKET_CIPHER_FindCipherEnd
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description:  搜索密文尾部标识
* @caution:  find:1  not find:0
*/
static int LOCKET_CIPHER_FindCipherEnd (IN char *pcInput, IN int iInputLen, OUT int *piEndPos)
{
    int i = 0, j = 0, iFind = 0;

    if ((NULL == pcInput) || (0 == iInputLen) || (NULL == piEndPos))
    {
        return iFind;
    }

    char szPattern[ENCRYPT_TAG_LEN] = ENCRYPT_SUFFIX_TAG;

    for (i = 0; i < iInputLen; i++)
    {
        j = 0;
        for (j = 0; j < sizeof (szPattern); j++)
        {
            if (pcInput[i + j] == szPattern[j])
            {
                continue;
            }
            else
            {
                break;
            }
        }

        if (j == sizeof (szPattern))
        {
            iFind = 1;
            *piEndPos = i + j;
            break;
        }
    }

    return iFind;
}

/**
* @Function:LOCKET_CIPHER_MatchHeader
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: 解析头标识
* @caution: 
*/
static int LOCKET_CIPHER_MatchHeader (IN DECRYPT_STATE_S *pstState, IN char *pcData, IN int iDataLen, OUT int *piUsedBytes)
{
    if ((NULL == pstState) || (NULL == pcData) || 
        (0 == iDataLen) || (NULL == piUsedBytes))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr           = ERR_COMMON_SUCCESS;
    int iNeedMoreBits  = 0;
    int *piOffSet      = &pstState->iHdrParseOffSet;
    char *pcHdrPasrseBuffer = pstState->szHdrParseBuf;

    iNeedMoreBits = (HEADER_TAG_LEN - *piOffSet);
    if (iDataLen > iNeedMoreBits)
    {
        memcpy (pcHdrPasrseBuffer + *piOffSet, pcData, iNeedMoreBits);
        *piOffSet += iNeedMoreBits;
        *piUsedBytes = iNeedMoreBits;
    }
    else
    {
        /* 缓冲内容仍然不够解析，需要继续填充 */
        memcpy (pcHdrPasrseBuffer + *piOffSet, pcData, iDataLen);
        *piOffSet += iDataLen;
        return ERR_STREAM_NEED_MORE_BITS;
    }

    char szHead[HEADER_TAG_LEN] = HEADER_PREFIX_TAG;
    if (0 != memcmp (pcHdrPasrseBuffer, szHead, sizeof (szHead)))
    {
        iErr = ERR_STREAM_INVALID_HEADER;
    }

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_MatchMetaLen
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: 解析meta长度标识
* @caution: 
*/
static int LOCKET_CIPHER_MatchMetaLen (IN DECRYPT_STATE_S *pstState, IN char *pcData, IN int iDataLen, OUT int *piUsedBytes, OUT int *piMetaLen)
{
    if ((NULL == pstState) || (NULL == pcData) || (0 == iDataLen) || 
        (NULL == piUsedBytes) || (NULL == piMetaLen))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr           = ERR_COMMON_SUCCESS;
    int iNeedMoreBits  = 0;
    int *piOffSet      = &pstState->iMetaLenParseOffSet;
    char *pcMetaLenBuf = pstState->szMetaLenParseBuf;

    iNeedMoreBits = (META_LEN_SIZE - *piOffSet);
    if (iDataLen > iNeedMoreBits)
    {
        memcpy (pcMetaLenBuf + *piOffSet, pcData, iNeedMoreBits);
        *piOffSet += iNeedMoreBits;
        *piUsedBytes = iNeedMoreBits;
    }
    else
    {
        /* 缓冲内容仍然不够解析，需要继续填充 */
        memcpy (pcMetaLenBuf + *piOffSet, pcData, iDataLen);
        *piOffSet += iDataLen;
        return ERR_STREAM_NEED_MORE_BITS;
    }

    int iMetaLen = atoi (pcMetaLenBuf);
    *piMetaLen += iMetaLen;

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_MatchMeta
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: 解析meta内容
* @caution: 返回的出参数，仅包含meta信息的JSON部分，不包含头和尾部
*/
static int LOCKET_CIPHER_MatchMeta (IN DECRYPT_STATE_S *pstState, IN char *pcData, IN int iDataLen, IN int iMetaSize, OUT int *piUsedBytes, OUT char* pcMetaBody)
{
    if ((NULL == pstState) || (NULL == pcData) || (0 == iDataLen) || 
        (NULL == piUsedBytes) || (NULL == pcMetaBody))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr           = ERR_COMMON_SUCCESS;
    int iNeedMoreBits  = 0;
    int *piOffSet      = &pstState->iMetaParseOffSet;
    char *pcMeta       = pstState->szMetaParseBuf;

    iNeedMoreBits = (iMetaSize - *piOffSet);
    if (iDataLen > iNeedMoreBits)
    {
        memcpy (pcMeta + *piOffSet, pcData, iNeedMoreBits);
        *piOffSet += iNeedMoreBits;
        *piUsedBytes = iNeedMoreBits;
    }
    else
    {
        memcpy (pcMeta + *piOffSet, pcData, iDataLen);
        *piOffSet += iDataLen;
        return ERR_STREAM_NEED_MORE_BITS;
    }

    memcpy (pcMetaBody, pcMeta + META_TAG_LEN,  iMetaSize - 2 * META_TAG_LEN);

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_MatchCipherTextStart
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: 解析密文起始标识
* @caution: 
*/
static int LOCKET_CIPHER_MatchCipherTextStart (IN DECRYPT_STATE_S *pstState, IN char *pcData, IN int iDataLen, OUT int *piUsedBytes)
{
    if ((NULL == pstState) || (NULL == pcData) || 
        (0 == iDataLen) || (NULL == piUsedBytes))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr           = ERR_COMMON_SUCCESS;
    int iNeedMoreBits  = 0;
    int *piOffSet      = &pstState->iCipherPrefixParseOffSet;
    char *pcCipherPrefixBuf = pstState->szCipherPrefixParseBuf;

    iNeedMoreBits = (ENCRYPT_TAG_LEN- *piOffSet);
    if (iDataLen > iNeedMoreBits)
    {
        memcpy (pcCipherPrefixBuf + *piOffSet, pcData, iNeedMoreBits);
        *piOffSet += iNeedMoreBits;
        *piUsedBytes = iNeedMoreBits;
    }
    else
    {
        /* 缓冲内容仍然不够解析，需要继续填充 */
        memcpy (pcCipherPrefixBuf + *piOffSet, pcData, iDataLen);
        *piOffSet += iDataLen;
        return ERR_STREAM_NEED_MORE_BITS;
    }

    char szEncryptTag[ENCRYPT_TAG_LEN] = ENCRYPT_PREFIX_TAG;
    if (0 != memcmp (pcCipherPrefixBuf, szEncryptTag, sizeof (szEncryptTag)))
    {
        iErr = ERR_STREAM_INVALID_HEADER;
    }

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_DecrytCipherText
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: 解码密文内容
* @caution: 
*/
static int LOCKET_CIPHER_DecrytCipherText (IN CRYPT_HANDLE hCrypt,  IN char *pcData, IN int iDataLen, IN META_S *pstMeta)
{
    if ((NULL == hCrypt) || (NULL == pcData) || (0 == iDataLen) || (NULL == pstMeta))
    {
        return ERR_COMMON_INVALID_PARAM;
    }

    int iErr                            = ERR_COMMON_SUCCESS;
    static const EVP_CIPHER *pstCipher  = NULL;
    STREAM_CTX_S *pstCtx                = (STREAM_CTX_S*) hCrypt;
    DECRYPT_STATE_S *pstState             = &pstCtx->stDecState;
    int *piOffSet                       = &pstState->iCipherDataParseOffset;
    unsigned char *pcCipherDataParseBuf = pstState->szCipherDataParseBuf;

    if (0 == pstState->iStartDec)
    {
        /* 解密操作 */
        pstCipher = EVP_get_cipherbyname(CRYPT_ALGORITHM);
        iErr = EVP_CipherInit_ex(pstCtx->pstCipherCtx, pstCipher, NULL, 
                pstMeta->stCipher.szKey, pstMeta->stCipher.szIv, 0);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherInit_ex failed. %s", LOCKET_ERR_GetString());
            return iErr;
        }
        pstState->iStartDec = 1;
    }    

    memcpy (pcCipherDataParseBuf + *piOffSet, pcData, iDataLen);
    *piOffSet += iDataLen;
    if (*piOffSet <= TAG_LEN)
    {
        return ERR_STREAM_NEED_MORE_BITS;
    }

    int iOutLen  = 0;
    int iOutLen2 = 0;
    int iEndPos = 0;
    int bFind = LOCKET_CIPHER_FindCipherEnd ((char*) pcCipherDataParseBuf, *piOffSet, &iEndPos);
    unsigned char szOutput[DECRYPT_BLOCK_SIZE + TAG_LEN] = {0};
    CB_PARAM_S stParam;
    if (1 == bFind)
    {
        iErr = EVP_CipherUpdate(pstCtx->pstCipherCtx, szOutput, &iOutLen, pcCipherDataParseBuf, *piOffSet - TAG_LEN);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherUpdate failed. %s", LOCKET_ERR_GetString());
            return iErr;
        }

        stParam.pcData = (char*) szOutput;
        stParam.iParamLen = iOutLen;

        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

        iErr = EVP_CipherFinal_ex(pstCtx->pstCipherCtx, szOutput + iOutLen, &iOutLen2);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherFinal_ex failed. %s", LOCKET_ERR_GetString());
            return iErr;
        }
        stParam.pcData = (char*) (szOutput + iOutLen);
        stParam.iParamLen = iOutLen2;

        if (0 != iOutLen)
        {
            (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, NULL);
        }

        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_FINISH, NULL);

        return ERR_STREAM_DECODE_FINISH;
    }
    else
    {
        iErr = EVP_CipherUpdate(pstCtx->pstCipherCtx, szOutput, &iOutLen, pcCipherDataParseBuf, *piOffSet - TAG_LEN);
        if (ERR_COMMON_SUCCESS != iErr)
        {
            LOCKET_LOGERROR ("EVP_CipherUpdate failed. %s", LOCKET_ERR_GetString());
            return iErr;
        }
        stParam.pcData = (char*) szOutput;
        stParam.iParamLen = iOutLen;
        (*pstCtx->stCryptInfo.pfCryptCBFunc) (MSG_CRYPT_DATA, (void*) &stParam);

        /* 拷贝最后的6字节到头部，用于下一次的解析 */
        char szTmpBuffer[TAG_LEN] = {0}; /* 为了防止内存覆盖，用一个临时buffer保存 */
        memcpy (szTmpBuffer, pcCipherDataParseBuf + *piOffSet - TAG_LEN, sizeof (szTmpBuffer));
        memcpy (pcCipherDataParseBuf, szTmpBuffer, sizeof (szTmpBuffer));
        *piOffSet = sizeof (szTmpBuffer);
    }

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_StreamDecryptUpdate
* @Author: guojianchuan/max
* @Date: 2016-07-25
* @Description: AES decrypt for stream
* @caution: 
*/
int LOCKET_CIPHER_StreamDecryptUpdate (CRYPT_HANDLE hCrypt, char *pcData, int iLen)
{
    if((NULL == hCrypt) || (NULL == pcData) || (0 == iLen))
    {
        return ERR_COMMON_INVALID_PARAM;
    }
    
    int iErr                 = ERR_COMMON_SUCCESS;
    STREAM_CTX_S *pstCtx     = (STREAM_CTX_S*) hCrypt;
    DECRYPT_STATE_S *pstState  = &pstCtx->stDecState;
    META_S *pstMeta          = &pstState->stMeta;
    int iStep                = pstState->iStep;

    int iDataLen = 0;
    int iBlocks = CALC_BLOCK_NUM(iLen,DECRYPT_BLOCK_SIZE);
    int i = 0;
    char *pcOffSet = NULL;
    int iUsedBytes = 0;
    int iMetaLen = 0;
    char szMetaBody[META_SIZE] = {0};

    for (i = 0; i < iBlocks; i++)
    {
        pcOffSet = pcData + i * DECRYPT_BLOCK_SIZE;
        iDataLen = iLen - i * DECRYPT_BLOCK_SIZE;

        if (PARSE_HEADER == iStep)
        {
            iErr = LOCKET_CIPHER_MatchHeader (pstState, pcOffSet, iDataLen, &iUsedBytes);
            if (ERR_STREAM_NEED_MORE_BITS == iErr)
            {
                continue; 
            }
            else if (ERR_COMMON_SUCCESS == iErr)
            {
                iStep = PARSE_META_LEN;
                pcOffSet += iUsedBytes;
                iDataLen -= iUsedBytes;
            }
            else
            {
                break;
            }
        }

        if (PARSE_META_LEN == iStep)
        {
            iErr = LOCKET_CIPHER_MatchMetaLen (pstState, pcOffSet, iDataLen, &iUsedBytes, &iMetaLen);
            if (ERR_STREAM_NEED_MORE_BITS == iErr)
            {
                continue; 
            }
            else if (ERR_COMMON_SUCCESS == iErr)
            {
                iStep = PARSE_META_START;
                pcOffSet += iUsedBytes;
                iDataLen -= iUsedBytes;
            }
            else
            {
                break;
            }
        }

        if (PARSE_META_START == iStep)
        {
            iErr = LOCKET_CIPHER_MatchMeta (pstState, pcOffSet, iDataLen, iMetaLen, &iUsedBytes, szMetaBody);
            if (ERR_STREAM_NEED_MORE_BITS == iErr)
            {
                continue; 
            }
            else if (ERR_COMMON_SUCCESS == iErr)
            {
                iStep = PARSE_DATA_START;
                pcOffSet += iUsedBytes;
                iDataLen -= iUsedBytes;
            }
            else
            {
                break;
            }

            iErr = LOCKET_CIPHER_ParseFileMeta(szMetaBody, pstMeta);
            if (ERR_COMMON_SUCCESS != iErr)
            {
                break;
            }
        }

        if (PARSE_DATA_START == iStep)
        {
            iErr = LOCKET_CIPHER_MatchCipherTextStart (pstState, pcOffSet, iDataLen, &iUsedBytes);
            if (ERR_STREAM_NEED_MORE_BITS == iErr)
            {
                continue; 
            }
            else if (ERR_COMMON_SUCCESS == iErr)
            {
                iStep = PARSE_DATA;
                pcOffSet += iUsedBytes;
                iDataLen -= iUsedBytes;
            }
            else
            {
                break;
            }
        }

        if (PARSE_DATA == iStep)
        {
            iErr = LOCKET_CIPHER_DecrytCipherText (hCrypt, pcOffSet, iDataLen, pstMeta);
            if (ERR_STREAM_NEED_MORE_BITS == iErr)
            {
                continue; 
            }
            else if (ERR_STREAM_DECODE_FINISH == iErr)
            {
                iStep = PARSE_HEADER;
            }
            else if (ERR_COMMON_SUCCESS != iErr)
            {
                break;
            }
        }
    }

    return iErr;
}

/**
* @Function:LOCKET_CIPHER_StreamCryptFree
* @Author: guojianchuan/max
* @Date: 2016-07-21
* @Description: 流加解密完成后需要调用此函数释放资源
* @caution: 
*/
void LOCKET_CIPHER_StreamCryptFree (CRYPT_HANDLE hCrypt)
{
    if (NULL == hCrypt)
    {
        return;
    }

    STREAM_CTX_S *pstCtx = (STREAM_CTX_S*) hCrypt;
    DECRYPT_STATE_S *pstState = &pstCtx->stDecState;

    EVP_CIPHER_CTX_free (pstCtx->pstCipherCtx);
    LOCKET_free ((void**) &pstCtx->pcData);
    LOCKET_free ((void**) &pstCtx);

    return;
}
